home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 14 / Example 14.1 / app.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  22.9 KB  |  812 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 14.1: Game Brains!                                //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include "debug.h"
  9. #include "shader.h"
  10. #include "terrain.h"
  11. #include "camera.h"
  12. #include "mouse.h"
  13. #include "player.h"
  14. #include "effect.h"
  15. #include "particles.h"
  16.  
  17. //Effect Pool
  18. extern std::vector<EFFECT*> effects;
  19.  
  20. class APPLICATION
  21. {
  22.     public:
  23.         APPLICATION();
  24.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  25.         HRESULT Update(float deltaTime);
  26.         HRESULT Render();
  27.         HRESULT Cleanup();
  28.         HRESULT Quit();
  29.         DWORD FtoDword(float f){return *((DWORD*)&f);}
  30.  
  31.         void AddPlayers(int noPlayers);
  32.         void FogOfWar();
  33.         void UpdateMiniMap();
  34.         void RenderMiniMap(RECT dest);
  35.  
  36.     private:
  37.         IDirect3DDevice9* m_pDevice; 
  38.         TERRAIN m_terrain;
  39.         CAMERA m_camera;
  40.         MOUSE m_mouse;
  41.         std::vector<PLAYER*> m_players;
  42.  
  43.         bool m_wireframe, m_paused;
  44.         ID3DXFont *m_pFont;            
  45.         DWORD m_time;
  46.         int m_fps, m_lastFps;
  47.         int m_thisPlayer;
  48.         float m_gameSpeed;
  49.  
  50.         HWND m_mainWindow;
  51.         ID3DXLine *m_pLine;
  52.  
  53.         //Fog-of-War variables
  54.         IDirect3DTexture9 *m_pVisibleTexture, *m_pVisitedTexture;
  55.         SHADER m_visitedShader, m_FogOfWarShader;
  56.         ID3DXSprite *m_pSprite;
  57.         bool m_firstFogOfWar;
  58.  
  59.         //Minimap
  60.         IDirect3DTexture9 *m_pMiniMap;
  61.         IDirect3DTexture9 *m_pMiniMapBorder;
  62.         SHADER m_miniMapShader;
  63.         RECT m_miniMapRect;
  64. };
  65.  
  66. D3DRECT SetRect(long x1, long y1, long x2, long y2)
  67. {
  68.     D3DRECT r;
  69.     r.x1 = x1;
  70.     r.y1 = y1;
  71.     r.x2 = x2;
  72.     r.y2 = y2;
  73.     return r;
  74. }
  75.  
  76. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  77. {
  78.     APPLICATION app;
  79.  
  80.     if(FAILED(app.Init(hInstance, 800, 600, true)))return 0;
  81.  
  82.     MSG msg;
  83.     memset(&msg, 0, sizeof(MSG));
  84.     int startTime = timeGetTime(); 
  85.  
  86.     while(msg.message != WM_QUIT)
  87.     {
  88.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  89.         {
  90.             ::TranslateMessage(&msg);
  91.             ::DispatchMessage(&msg);
  92.         }
  93.         else
  94.         {    
  95.             int t = timeGetTime();
  96.             float deltaTime = (t - startTime)*0.001f;
  97.  
  98.             app.Update(deltaTime);
  99.             app.Render();
  100.  
  101.             startTime = t;
  102.         }
  103.     }
  104.  
  105.     app.Cleanup();
  106.  
  107.     return msg.wParam;
  108. }
  109.  
  110. APPLICATION::APPLICATION()
  111. {
  112.     m_pDevice = NULL; 
  113.     m_mainWindow = 0;
  114.     m_wireframe = false;
  115.     srand(GetTickCount());
  116.     m_fps = m_lastFps = m_thisPlayer = 0;
  117.     m_time = GetTickCount();
  118.     m_pLine = NULL;
  119.     m_firstFogOfWar = true;
  120.     m_gameSpeed = 3.0f;
  121.     m_paused = false;
  122.  
  123.     m_pVisibleTexture = m_pVisitedTexture = m_pMiniMap = NULL;
  124.     m_pMiniMapBorder = NULL;
  125. }
  126.  
  127. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  128. {
  129.     debug.Print("Application initiated");
  130.  
  131.     //Create Window Class
  132.     WNDCLASS wc;
  133.     memset(&wc, 0, sizeof(WNDCLASS));
  134.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  135.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  136.     wc.hInstance     = hInstance;
  137.     wc.lpszClassName = "D3DWND";
  138.  
  139.     //Register Class and Create new Window
  140.     RegisterClass(&wc);
  141.     m_mainWindow = CreateWindow("D3DWND", "Example 14.1: Game Brains!", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  142.     SetCursor(NULL);
  143.     ShowWindow(m_mainWindow, SW_SHOW);
  144.     UpdateWindow(m_mainWindow);
  145.  
  146.     //Create IDirect3D9 Interface
  147.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  148.  
  149.     if(d3d9 == NULL)
  150.     {
  151.         debug.Print("Direct3DCreate9() - FAILED");
  152.         return E_FAIL;
  153.     }
  154.  
  155.     //Check that the Device supports what we need from it
  156.     D3DCAPS9 caps;
  157.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  158.  
  159.     //Hardware Vertex Processing or not?
  160.     int vp = 0;
  161.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  162.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  163.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  164.  
  165.     //Check vertex & pixelshader versions
  166.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  167.     {
  168.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  169.     }
  170.  
  171.     //Set D3DPRESENT_PARAMETERS
  172.     D3DPRESENT_PARAMETERS d3dpp;
  173.     d3dpp.BackBufferWidth            = width;
  174.     d3dpp.BackBufferHeight           = height;
  175.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  176.     d3dpp.BackBufferCount            = 1;
  177.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  178.     d3dpp.MultiSampleQuality         = 0;
  179.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  180.     d3dpp.hDeviceWindow              = m_mainWindow;
  181.     d3dpp.Windowed                   = windowed;
  182.     d3dpp.EnableAutoDepthStencil     = true; 
  183.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  184.     d3dpp.Flags                      = 0;
  185.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  186.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  187.  
  188.     //Create the IDirect3DDevice9
  189.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  190.                                  vp, &d3dpp, &m_pDevice)))
  191.     {
  192.         debug.Print("Failed to create IDirect3DDevice9");
  193.         return E_FAIL;
  194.     }
  195.  
  196.     //Release IDirect3D9 interface
  197.     d3d9->Release();
  198.  
  199.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  200.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  201.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  202.  
  203.     LoadObjectResources(m_pDevice);
  204.     LoadMapObjectResources(m_pDevice);
  205.     LoadUnitResources(m_pDevice);
  206.     LoadBuildingResources(m_pDevice);
  207.     LoadPlayerResources(m_pDevice);
  208.     LoadEffectResources(m_pDevice);
  209.     LoadParticleResources(m_pDevice);
  210.  
  211.     m_mouse.InitMouse(m_pDevice, m_mainWindow);
  212.  
  213.     m_camera.Init(m_pDevice);
  214.     m_camera.m_fov = 0.6f;
  215.     m_camera.m_radius = 50.0f;
  216.  
  217.     D3DXCreateLine(m_pDevice, &m_pLine);
  218.  
  219.     //Set sampler state
  220.     for(int i=0;i<8;i++)
  221.     {
  222.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  223.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  224.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  225.     }
  226.  
  227.     //Create Fog-of-war textures
  228.     if(FAILED(m_pDevice->CreateTexture(256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pVisibleTexture, NULL)))debug.Print("Failed to create texture: m_pVisibleTexture");
  229.     if(FAILED(m_pDevice->CreateTexture(256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pVisitedTexture, NULL)))debug.Print("Failed to create texture: m_pVisitedTexture");
  230.  
  231.     //Fog-of-war Shaders
  232.     m_visitedShader.Init(m_pDevice, "shaders/visited.ps", PIXEL_SHADER);
  233.     m_FogOfWarShader.Init(m_pDevice, "shaders/FogOfWar.ps", PIXEL_SHADER);
  234.     m_firstFogOfWar = true;
  235.  
  236.     //Create Minimap
  237.     if(FAILED(m_pDevice->CreateTexture(256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pMiniMap, NULL)))debug.Print("Failed to create texture: m_pMinimap");
  238.     if(FAILED(D3DXCreateTextureFromFile(m_pDevice, "textures/minimap.dds", &m_pMiniMapBorder)))debug.Print("Could not load minimap.dds");
  239.     m_miniMapShader.Init(m_pDevice, "shaders/minimap.ps", PIXEL_SHADER);
  240.     RECT r = {611, 9, 791, 189};
  241.     m_miniMapRect = r;
  242.  
  243.     //Sprite 
  244.     D3DXCreateSprite(m_pDevice, &m_pSprite);
  245.  
  246.     //Init Terrain
  247.     m_terrain.Init(m_pDevice, INTPOINT(150,150));
  248.  
  249.     //Add Players
  250.     AddPlayers(4);
  251.     
  252.     return S_OK;
  253. }
  254.  
  255. HRESULT APPLICATION::Update(float deltaTime)
  256. {
  257.     //Remove dead effects
  258.     std::vector<EFFECT*>::iterator i;
  259.  
  260.     for(i=effects.begin();i != effects.end();)
  261.     {
  262.         if((*i)->isDead())
  263.         {
  264.             delete (*i);
  265.             effects.erase(i);
  266.         }
  267.         else 
  268.         {
  269.             (*i)->Update(deltaTime * m_gameSpeed);
  270.             i++;
  271.         }
  272.     }
  273.  
  274.     //Pause game
  275.     if(m_paused && m_gameSpeed > 0.0f)
  276.     {
  277.         m_gameSpeed -= deltaTime * 2.0f;
  278.         if(m_gameSpeed < 0.0f)m_gameSpeed = 0.0f;
  279.     }
  280.     else if(!m_paused && m_gameSpeed < 3.0f)
  281.     {
  282.         m_gameSpeed += deltaTime * 2.0f;
  283.         if(m_gameSpeed > 3.0f)m_gameSpeed = 3.0f;
  284.     }
  285.     
  286.  
  287.     //Update Players
  288.     for(int i=0;i<m_players.size();i++)
  289.         if(m_players[i] != NULL)
  290.             m_players[i]->UpdateMapObjects(deltaTime * m_gameSpeed);
  291.  
  292.     //Update Fog-of-War
  293.     FogOfWar();    
  294.  
  295.     //Control camera
  296.     m_camera.Update(m_mouse, m_terrain, deltaTime);
  297.     m_mouse.Update(&m_terrain);
  298.  
  299.     //Update SightMatrices & visible variables
  300.     if(m_terrain.m_updateSight)
  301.     {
  302.         m_terrain.m_updateSight = false;
  303.  
  304.         if(m_thisPlayer < m_players.size() && m_players[m_thisPlayer] != NULL)
  305.             m_terrain.UpdateSightMatrices(m_players[m_thisPlayer]->m_mapObjects);
  306.  
  307.         for(int i=0;i<m_players.size();i++)
  308.             if(m_players[i] != NULL)
  309.                 m_players[i]->IsMapObjectsVisible();
  310.  
  311.         //Update Minimap        
  312.         UpdateMiniMap();
  313.     }
  314.  
  315.     //Keyboard input
  316.     if(KEYDOWN('W'))
  317.     {
  318.         //m_wireframe = !m_wireframe;
  319.         //Sleep(300);
  320.     }
  321.     else if(KEYDOWN(VK_SPACE))
  322.     {
  323.         if(m_gameSpeed == 0.0f || m_gameSpeed == 3.0f)
  324.             m_paused = !m_paused;
  325.     }
  326.     else if(KEYDOWN(VK_ESCAPE))
  327.     {
  328.         Quit();
  329.     }
  330.  
  331.     return S_OK;
  332. }    
  333.  
  334. HRESULT APPLICATION::Render()
  335. {
  336.     // Clear the viewport
  337.     m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  338.  
  339.     //FPS Calculation
  340.     m_fps++;
  341.     if(GetTickCount() - m_time > 1000)
  342.     {
  343.         m_lastFps = m_fps;
  344.         m_fps = 0;
  345.         m_time = GetTickCount();
  346.     }
  347.  
  348.     // Begin the scene 
  349.     if(SUCCEEDED(m_pDevice->BeginScene()))
  350.     {
  351.         if(m_wireframe)m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);    
  352.         else m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  353.  
  354.         //Render terrain
  355.         m_terrain.Render(m_camera);
  356.  
  357.         //Render units and buildings
  358.         for(int i=0;i<m_players.size();i++)
  359.             if(m_players[i] != NULL)
  360.                 m_players[i]->RenderMapObjects(m_camera);
  361.  
  362.         //Render Effects
  363.         for(int i=0;i<effects.size();i++)
  364.             if(effects[i] != NULL)
  365.                 effects[i]->Render();
  366.  
  367.         //Render Minimap
  368.         RenderMiniMap(m_miniMapRect);
  369.  
  370.         RECT r[] = {{10, 580, 0, 0}, {520, 10, 0, 0}, {10, 10, 0, 0}, {5, 20, 0, 0}};
  371.         m_pFont->DrawText(NULL, "Space: Pause Game", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  372.  
  373.         //FPS
  374.         char number[50];
  375.         std::string text = "FPS: ";
  376.         text += _itoa(m_lastFps, number, 10);
  377.         m_pFont->DrawText(NULL, text.c_str(), -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  378.  
  379.         m_pFont->DrawText(NULL, "Kills:", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  380.         m_pFont->DrawText(NULL, "-------------", -1, &r[3], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  381.  
  382.         //Team Kill Score
  383.         for(int i=0;i<m_players.size();i++)
  384.         {
  385.             if(i == 0)text = "RED: ";
  386.             if(i == 1)text = "GREEN: ";
  387.             if(i == 2)text = "BLUE: ";
  388.             if(i == 3)text = "YELLOW: ";
  389.  
  390.             text += itoa(m_players[i]->m_numKills, number, 10);
  391.             RECT rc = {10, 35 + i * 20, 0, 0};
  392.             m_pFont->DrawText(NULL, text.c_str(), -1, &rc, DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  393.         }        
  394.  
  395.         m_mouse.Paint();
  396.  
  397.         // End the scene.
  398.         m_pDevice->EndScene();
  399.         m_pDevice->Present(0, 0, 0, 0);
  400.     }
  401.  
  402.     return S_OK;
  403. }
  404.  
  405. HRESULT APPLICATION::Cleanup()
  406. {
  407.     try
  408.     {
  409.         m_terrain.Release();
  410.  
  411.         UnloadObjectResources();
  412.         UnloadMapObjectResources();
  413.         UnloadUnitResources();
  414.         UnloadBuildingResources();
  415.         UnloadPlayerResources();
  416.         UnloadEffectResources();
  417.         UnloadParticleResources();
  418.  
  419.         if(m_pVisibleTexture)m_pVisibleTexture->Release();
  420.         if(m_pVisitedTexture)m_pVisitedTexture->Release();
  421.  
  422.         if(m_pMiniMap)m_pMiniMap->Release();
  423.         if(m_pMiniMapBorder)m_pMiniMapBorder->Release();
  424.  
  425.         for(int i=0;i<m_players.size();i++)
  426.             if(m_players[i] != NULL)
  427.                 delete m_players[i];
  428.         m_players.clear();
  429.  
  430.         m_pFont->Release();
  431.         m_pSprite->Release();
  432.         m_pLine->Release();
  433.  
  434.         m_pDevice->Release();
  435.  
  436.         debug.Print("Application terminated");
  437.     }
  438.     catch(...){}
  439.  
  440.     return S_OK;
  441. }
  442.  
  443. HRESULT APPLICATION::Quit()
  444. {
  445.     ::DestroyWindow(m_mainWindow);
  446.     ::PostQuitMessage(0);
  447.     return S_OK;
  448. }
  449.  
  450. void APPLICATION::AddPlayers(int noPlayers)
  451. {
  452.     m_thisPlayer = 0;
  453.  
  454.     for(int i=0;i<m_players.size();i++)
  455.         if(m_players[i] != NULL)
  456.             delete m_players[i];
  457.     m_players.clear();
  458.  
  459.     INTPOINT startLocations[] = {INTPOINT(30,30), INTPOINT(120,30), INTPOINT(30,120), INTPOINT(120,120)};
  460.     //INTPOINT startLocations[] = {INTPOINT(15,15), INTPOINT(50,50), INTPOINT(30,120), INTPOINT(120,120)};
  461.  
  462.     D3DXVECTOR4 teamCols[] = {D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f), D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f),
  463.                               D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f), D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f)};
  464.     
  465.     int controllers[] = {COMPUTER, COMPUTER, COMPUTER, COMPUTER};
  466.  
  467.     if(noPlayers < 2)noPlayers = 2;
  468.     if(noPlayers > 4)noPlayers = 4;
  469.  
  470.     for(int i=0;i<noPlayers;i++)
  471.     {
  472.         m_terrain.Progress("Creating Players", i / (float)noPlayers);
  473.         m_players.push_back(new PLAYER(i, controllers[i], teamCols[i], startLocations[i], &m_terrain, m_pDevice));    
  474.     }
  475.  
  476.     //Center camera focus on the team...
  477.     m_camera.m_focus = m_terrain.GetWorldPos(m_players[m_thisPlayer]->GetCenter());
  478. }
  479.  
  480. void APPLICATION::FogOfWar()
  481. {
  482.     try
  483.     {
  484.         if(m_pVisibleTexture == NULL || m_pVisitedTexture == NULL)return;
  485.         
  486.         //Set orthogonal rendering view & projection
  487.         m_terrain.SetOrthogonalView();
  488.  
  489.         //Retrieve the surface of the back buffer
  490.         IDirect3DSurface9 *backSurface = NULL;
  491.         m_pDevice->GetRenderTarget(0, &backSurface);
  492.  
  493.         //Render the Visible Texture here...
  494.         {
  495.             //Set texture stages and Renderstates
  496.             m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  497.             m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
  498.             m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_ADD);
  499.             m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  500.             m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  501.             m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
  502.  
  503.             m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
  504.             m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  505.             m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  506.             m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
  507.             
  508.             //Get the surface of the m_pVisibleTexture
  509.             IDirect3DSurface9 *visibleSurface = NULL;            
  510.             m_pVisibleTexture->GetSurfaceLevel(0, &visibleSurface);            
  511.  
  512.             //Set render target to the visible surface
  513.             m_pDevice->SetRenderTarget(0, visibleSurface);
  514.  
  515.             //Clear render target to black
  516.             m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  517.             //m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
  518.  
  519.             m_pDevice->BeginScene();
  520.  
  521.             //Render the sightTexture for all map objects in thisPlayer.
  522.             if(m_thisPlayer < m_players.size() && m_players[m_thisPlayer] != NULL)
  523.                 for(int u=0;u<m_players[m_thisPlayer]->m_mapObjects.size();u++)
  524.                     if(m_players[m_thisPlayer]->m_mapObjects[u] != NULL)
  525.                         m_players[m_thisPlayer]->m_mapObjects[u]->RenderSightMesh();
  526.  
  527.             m_pDevice->EndScene();
  528.  
  529.             //Restore renderstates etc.
  530.             m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
  531.             m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
  532.             m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  533.             m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  534.  
  535.             //Release visible surface
  536.             visibleSurface->Release();
  537.         }
  538.  
  539.         //Render the Visited Texture here...
  540.         {
  541.             IDirect3DSurface9 *visitedSurface = NULL;
  542.             m_pVisitedTexture->GetSurfaceLevel(0, &visitedSurface);
  543.  
  544.             //Render to the visted texture
  545.             m_pDevice->SetRenderTarget(0, visitedSurface);
  546.             if(m_firstFogOfWar)
  547.             {
  548.                 //m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  549.                 m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x88888888, 1.0f, 0);
  550.                 m_firstFogOfWar = false;
  551.             }
  552.  
  553.             m_pDevice->BeginScene();
  554.             m_pDevice->SetTexture(0, m_pVisibleTexture);
  555.             m_pDevice->SetTexture(1, m_pVisitedTexture);
  556.  
  557.             m_pSprite->Begin(0);
  558.             m_visitedShader.Begin();
  559.             m_pSprite->Draw(m_pVisibleTexture, NULL, NULL, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0xffffffff);
  560.             m_pSprite->End();
  561.             m_visitedShader.End();
  562.  
  563.             m_pDevice->EndScene();
  564.         
  565.             //Release visited surface
  566.             visitedSurface->Release();
  567.         }
  568.  
  569.         //Render the final FogOfWarTexture
  570.         {
  571.             //Get and set surface of the FogOfWarTexture...
  572.             IDirect3DSurface9 *FogOfWarSurface = NULL;
  573.             m_terrain.m_pFogOfWarTexture->GetSurfaceLevel(0, &FogOfWarSurface);
  574.             m_pDevice->SetRenderTarget(0, FogOfWarSurface);
  575.  
  576.             m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  577.             m_pDevice->BeginScene();
  578.  
  579.             //Set Textures
  580.             m_pDevice->SetTexture(0, m_pVisibleTexture);
  581.             m_pDevice->SetTexture(1, m_pVisitedTexture);
  582.             m_pDevice->SetTexture(2, m_terrain.m_pLightMap);
  583.  
  584.             //Draw to the Fog-of-War texture
  585.             m_pSprite->Begin(0);
  586.             m_FogOfWarShader.Begin();
  587.             m_pSprite->Draw(m_pVisibleTexture, NULL, NULL, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0xffffffff);
  588.             m_pSprite->End();
  589.             m_FogOfWarShader.End();
  590.  
  591.             m_pDevice->EndScene();
  592.  
  593.             //Release fog of war surface
  594.             FogOfWarSurface->Release();
  595.         }
  596.  
  597.         //Reset render target to back buffer
  598.         m_pDevice->SetRenderTarget(0, backSurface);
  599.         backSurface->Release();        
  600.     }
  601.     catch(...)
  602.     {
  603.         debug.Print("Error in APPLICATION::FogOfWar()");
  604.     }
  605. }
  606.  
  607. void APPLICATION::UpdateMiniMap()
  608. {
  609.     //Retrieve the surface of the back buffer
  610.     IDirect3DSurface9 *backSurface = NULL;
  611.     m_pDevice->GetRenderTarget(0, &backSurface);
  612.  
  613.     //Get and set surface of the FogOfWarTexture...
  614.     IDirect3DSurface9 *minimapSurface = NULL;
  615.     m_pMiniMap->GetSurfaceLevel(0, &minimapSurface);
  616.     m_pDevice->SetRenderTarget(0, minimapSurface);
  617.  
  618.     m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  619.     m_pDevice->BeginScene();
  620.  
  621.     //Set Textures
  622.     m_pDevice->SetTexture(0, m_terrain.m_pLandScape);
  623.     m_pDevice->SetTexture(1, m_terrain.m_pFogOfWarTexture);
  624.  
  625.     //Draw to the minimap texture
  626.     m_pSprite->Begin(0);
  627.     m_miniMapShader.Begin();
  628.     m_pSprite->Draw(m_terrain.m_pLandScape, NULL, NULL, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0xffffffff);
  629.     m_pSprite->End();
  630.     m_miniMapShader.End();
  631.  
  632.     m_pDevice->EndScene();
  633.  
  634.     //Draw units and buildings in the player team color
  635.     for(int p=0;p<m_players.size();p++)
  636.         if(m_players[p] != NULL)
  637.         {
  638.             std::vector<D3DRECT> rects;
  639.  
  640.             //Get rectangles in "Minimap Space"
  641.             for(int m=0;m<m_players[p]->m_mapObjects.size();m++)
  642.                 if(m_players[p]->m_mapObjects[m] != NULL && !m_players[p]->m_mapObjects[m]->m_dead)
  643.                     if(!m_players[p]->m_mapObjects[m]->m_isBuilding)
  644.                     {
  645.                         INTPOINT mappos = m_players[p]->m_mapObjects[m]->m_mappos;
  646.  
  647.                         //Only add units standing on visible tiles
  648.                         if(m_terrain.m_pVisibleTiles[mappos.x + mappos.y * m_terrain.m_size.x] || 1)
  649.                         {
  650.                             INTPOINT pos(256.0f * (mappos.x / (float)m_terrain.m_size.x), 
  651.                                          256.0f * (mappos.y / (float)m_terrain.m_size.y));
  652.  
  653.                             rects.push_back(SetRect(pos.x - 1, pos.y - 1, 
  654.                                                     pos.x + 2, pos.y + 2));
  655.                         }
  656.                     }
  657.                     else 
  658.                     {
  659.                         RECT r = m_players[p]->m_mapObjects[m]->GetMapRect(0);
  660.  
  661.                         //Add only those parts of the buildings standing on visited tiles
  662.                         for(int y=r.top;y<=r.bottom;y++)
  663.                             for(int x=r.left;x<=r.right;x++)
  664.                                 if(m_terrain.m_pVisitedTiles[x + y * m_terrain.m_size.x] || 1)
  665.                                 {
  666.                                     INTPOINT pos(256.0f * (x / (float)m_terrain.m_size.x), 
  667.                                                  256.0f * (y / (float)m_terrain.m_size.y));
  668.  
  669.                                     rects.push_back(SetRect(pos.x - 1, pos.y - 1, 
  670.                                                             pos.x + 2, pos.y + 2));
  671.                                 }
  672.                     }
  673.  
  674.             //Clear rectangles using the team color
  675.             if(!rects.empty())
  676.             {
  677.                 D3DXCOLOR c = D3DCOLOR_XRGB((int)(m_players[p]->m_teamColor.x * 255),
  678.                                             (int)(m_players[p]->m_teamColor.y * 255),
  679.                                             (int)(m_players[p]->m_teamColor.z * 255));
  680.                 
  681.                 m_pDevice->Clear(rects.size(), &rects[0], D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, c, 1.0f, 0);
  682.             }
  683.         }
  684.  
  685.     //Reset render target to back buffer
  686.     m_pDevice->SetRenderTarget(0, backSurface);
  687.  
  688.     //Release surfaces
  689.     backSurface->Release();
  690.     minimapSurface->Release();
  691. }
  692.  
  693. void APPLICATION::RenderMiniMap(RECT dest)
  694. {
  695.     float width = dest.right - dest.left;
  696.     float height = dest.bottom - dest.top;
  697.  
  698.     D3DXVECTOR2 scale = D3DXVECTOR2(width / 256.0f, 
  699.                                     height / 256.0f);
  700.     D3DXMATRIX sca;
  701.     D3DXMatrixScaling(&sca, scale.x, scale.y, 1.0f);
  702.     m_pSprite->SetTransform(&sca);
  703.  
  704.     m_pSprite->Begin(0);
  705.     m_pSprite->Draw(m_pMiniMap, NULL, NULL, &D3DXVECTOR3(dest.left / scale.x, dest.top / scale.y, 0.0f), 0xffffffff);
  706.     m_pSprite->End();
  707.  
  708.     D3DXMatrixIdentity(&sca);
  709.     m_pSprite->SetTransform(&sca);
  710.  
  711.     //Move camera using minimap
  712.     if(m_mouse.PressInRect(dest))
  713.     {
  714.         int x = ((m_mouse.x - dest.left) / width) * m_terrain.m_size.x;
  715.         int y = ((m_mouse.y - dest.top) / height) * m_terrain.m_size.y;
  716.  
  717.         m_camera.m_focus = m_terrain.GetWorldPos(INTPOINT(x, y));
  718.     }
  719.  
  720.     //Calculate m_camera frustum viewpoints
  721.     D3DXMATRIX view, proj, viewInverse;
  722.  
  723.     view = m_camera.GetViewMatrix();
  724.     proj = m_camera.GetProjectionMatrix();
  725.     
  726.     //fov_x & fov_y Determines the size of the frustum representation
  727.     float screenRatio = proj(0,0) / proj(1,1);
  728.     float fov_x = 0.4f;
  729.     float fov_y = fov_x * screenRatio;
  730.     
  731.     //Initialize the four rays
  732.     D3DXVECTOR3 org = D3DXVECTOR3(0.0f, 0.0f, 0.0f);    //Same origin
  733.  
  734.     //Four different directions
  735.     D3DXVECTOR3 dir[4] = {D3DXVECTOR3(-fov_x, fov_y, 1.0f),    
  736.                            D3DXVECTOR3(fov_x, fov_y, 1.0f),
  737.                           D3DXVECTOR3(fov_x, -fov_y, 1.0f),
  738.                           D3DXVECTOR3(-fov_x, -fov_y, 1.0f)};
  739.  
  740.     //Our resulting minimap coordinates
  741.     D3DXVECTOR2 points[5];
  742.  
  743.     //View matrix inverse
  744.     D3DXMatrixInverse(&viewInverse, 0, &view);
  745.     D3DXVec3TransformCoord(&org, &org, &viewInverse);
  746.  
  747.     //Ground plane
  748.     D3DXPLANE plane;
  749.     D3DXPlaneFromPointNormal(&plane, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  750.  
  751.     bool ok = true;
  752.  
  753.     //check where each ray intersects with the ground plane
  754.     for(int i=0;i<4 && ok;i++)
  755.     {
  756.         //Transform ray direction
  757.         D3DXVec3TransformNormal(&dir[i], &dir[i], &viewInverse);
  758.         D3DXVec3Normalize(&dir[i], &dir[i]);
  759.         dir[i] *= 1000.0f;
  760.  
  761.         //Find intersection point
  762.         D3DXVECTOR3 hit;
  763.         if(D3DXPlaneIntersectLine(&hit, &plane, &org, &dir[i]) == NULL)
  764.             ok = false;
  765.  
  766.         //Make sure the intersection point is on the positive side of the near plane
  767.         D3DXPLANE n = m_camera.m_frustum[4];
  768.         float distance = n.a * hit.x + n.b * hit.y + n.c * hit.z + n.d;
  769.         if(distance < 0.0f)ok = false;
  770.  
  771.         //Convert the intersection point to a minimap coordinate
  772.         if(ok)
  773.         {
  774.             points[i].x = (hit.x / (float)m_terrain.m_size.x) * width;
  775.             points[i].y = (-hit.z / (float)m_terrain.m_size.y) * height;
  776.         }
  777.     }
  778.  
  779.     //Set the end point to equal the starting point
  780.     points[4] = points[0];
  781.  
  782.     //Set viewport to destination rectangle only...
  783.     D3DVIEWPORT9 v1, v2;
  784.  
  785.     v1.X = dest.left;
  786.     v1.Y = dest.top;
  787.     v1.Width = width;
  788.     v1.Height = height;
  789.     v1.MinZ = 0.0f;
  790.     v1.MaxZ = 1.0f;
  791.  
  792.     m_pDevice->GetViewport(&v2);
  793.     m_pDevice->SetViewport(&v1);
  794.  
  795.     //Draw camera frustum in the minimap
  796.     if(ok)
  797.     {
  798.         m_pLine->SetWidth(1.0f);
  799.         m_pLine->SetAntialias(true);
  800.         m_pLine->Begin();
  801.         m_pLine->Draw(&points[0], 5, 0x44ffffff);
  802.         m_pLine->End();
  803.     }
  804.  
  805.     //Reset viewport
  806.     m_pDevice->SetViewport(&v2);
  807.  
  808.     //Draw minimap border
  809.     m_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
  810.     m_pSprite->Draw(m_pMiniMapBorder, NULL, NULL, &D3DXVECTOR3(v2.Width - 256, 0.0f, 0.0f), 0xffffffff);
  811.     m_pSprite->End();
  812. }